﻿using ServiceLayerManagement.Tool;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace ServiceLayerManagement
{
    public class AppHelper
    {
        /// <summary>
        /// 获取当前运行目录指定EXE文件的版本号
        /// </summary>
        /// <param name="m_ExeFile"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static string GetVersion(string m_ExeFile, int length = 2)
        {
            System.Text.StringBuilder builder = new System.Text.StringBuilder();
            FileVersionInfo myFileVersionInfo = FileVersionInfo.GetVersionInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, m_ExeFile));

            //string temp = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
            string[] arrList = myFileVersionInfo.FileVersion.Split('.');
            for (int i = 0; i < length; i++)
                builder.Append(arrList[i] + ".");

            return builder.ToString().Substring(0, builder.ToString().Length - 1);
        }

        /// <summary>
        /// 在UI线程中运行action代码
        /// </summary>
        /// <param name="action">action代码</param>
        [System.Diagnostics.DebuggerHidden]
        public static void RunInUI(FrameworkElement owner, Action action)
        {
            owner.Dispatcher.Invoke(new Action(() =>
            {
                action();
            }));
        }

        /// <summary>
        /// 在UI线程中运行action代码
        /// </summary>
        /// <typeparam name="T">窗体对象</typeparam>
        /// <param name="action"></param>
        [System.Diagnostics.DebuggerHidden]
        public static void RunInUI<T>(Action action) where T : ContentControl
        {
            T owner = Application.Current.Windows.Cast<Window>().FirstOrDefault(w => w is T) as T;
            owner.Dispatcher.Invoke(new Action(() =>
            {
                action();
            }));
        }

        /// <summary>
        /// 统一设置表格控件样式
        /// </summary>
        /// <param name="grid"></param>
        /// <param name="isShowIndicator">是否显示行号列</param>
        public static void SetDataGrid(DataGrid grid, bool isShowIndicator = true,bool isReadOnly=true)
        {
            grid.AutoGenerateColumns = false;
            grid.CanUserAddRows = false;
            //grid.CanUserResizeColumns = false;
            grid.CanUserSortColumns = false;
            grid.CanUserDeleteRows = false;
            grid.CanUserResizeRows = false;

            grid.RowHeight = 28;
            grid.VerticalContentAlignment = VerticalAlignment.Center;
            grid.HorizontalContentAlignment = HorizontalAlignment.Center;

            if (!isShowIndicator)
            {
                grid.HeadersVisibility = DataGridHeadersVisibility.Column;
            }
            else
            {
                grid.RowHeaderWidth = 28;
            }

            //设置网格文字对齐方式
            foreach (DataGridColumn column in grid.Columns)
            {
                string typeName = column.GetType().Name;
                switch (typeName)
                {
                    case "DataGridTextColumn":
                        Style styleRight = new Style(typeof(TextBlock));
                        Setter vs = new Setter(TextBlock.VerticalAlignmentProperty, grid.VerticalContentAlignment);
                        Setter hs = new Setter(TextBlock.HorizontalAlignmentProperty, grid.HorizontalContentAlignment);
                        styleRight.Setters.Add(vs);
                        styleRight.Setters.Add(hs);
                        DataGridTextColumn tc = column as DataGridTextColumn;                        
                        tc.ElementStyle = styleRight;
                        break;
                    case "DataGridCheckBoxColumn":
                        Style styleRight1 = new Style(typeof(CheckBox));
                        Setter vs1 = new Setter(TextBlock.VerticalAlignmentProperty, grid.VerticalContentAlignment);
                        Setter hs1 = new Setter(TextBlock.HorizontalAlignmentProperty, grid.HorizontalContentAlignment);
                        styleRight1.Setters.Add(vs1);
                        styleRight1.Setters.Add(hs1);
                        DataGridCheckBoxColumn chk = column as DataGridCheckBoxColumn;
                        chk.ElementStyle = styleRight1;
                        break;
                }
                column.IsReadOnly = isReadOnly;
            }

            Color color = (Color)ColorConverter.ConvertFromString("#CCC");
            var brush= new SolidColorBrush(color);
            grid.HorizontalGridLinesBrush = brush;
            grid.VerticalGridLinesBrush = brush;

            grid.LoadingRow += grid_LoadingRow;
        }

        static void grid_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.Header = e.Row.GetIndex() + 1;
        }

        /// <summary>
        /// 校验输入内容是否为IP地址
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static bool CheckIPAddress(string ip)
        {
            if (string.IsNullOrEmpty(ip) || ip.Length < 7 || ip.Length > 15) return false;

            string regformat = @"^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$";
            Regex regex = new Regex(regformat, RegexOptions.IgnoreCase);

            return regex.IsMatch(ip);
        }

        /// <summary>
        /// 根据通道编号生成通道名称
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        public static string GetChannelName(int i)
        {
            return $"通道{i.ToString().PadLeft(3, '0')}";
        }

        /// <summary>
        /// 判断Ip地址正确性
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static bool IsIPAddress(string ip)
        {

            if (string.IsNullOrEmpty(ip) || ip.Length < 7 || ip.Length > 15) return false;

            string regformat = @"^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$";

            Regex regex = new Regex(regformat, RegexOptions.IgnoreCase);

            return regex.IsMatch(ip);
        }

        /// <summary>
        /// 判断MAC地址正确性
        /// </summary>
        /// <param name="mac"></param>
        /// <returns></returns>
        public static bool IsMacAddress(string mac)
        {
            if (string.IsNullOrEmpty(mac) || mac.Length != 17) return false;

            string regformat = @"[0,9]|[a,z]|[A,Z][0,9]|[a,z]|[A,Z]:[0,9]|[a,z]|[A,Z][0,9]|[a,z]|[A,Z]:[0,9]|[a,z]|[A,Z][0,9]|[a,z]|[A,Z]:[0,9]|[a,z]|[A,Z][0,9]|[a,z]|[A,Z]:[0,9]|[a,z]|[A,Z][0,9]|[a,z]|[A,Z]:[0,9]|[a,z]|[A,Z][0,9]|[a,z]|[A,Z]";

            Regex regex = new Regex(regformat, RegexOptions.IgnoreCase);

            return regex.IsMatch(mac);

        }

        /// <summary>
        /// 字节数组转十六进制字符串
        /// </summary>
        /// <param name="arrByte"></param>
        /// <param name="reverse"></param>
        /// <returns></returns>
        public static string ConvertBytesToHex(byte[] arrByte, bool reverse)
        {
            StringBuilder sb = new StringBuilder();
            if (reverse)
                Array.Reverse(arrByte);
            foreach (byte b in arrByte)
                sb.AppendFormat("{0:x2}", b);
            return sb.ToString();
        }

        /// <summary>
        /// 十六进制字符串转字节数组
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte[] ConvertHexToBytes(string value)
        {
            int len = value.Length / 2;
            byte[] ret = new byte[len];
            for (int i = 0; i < len; i++)
                ret[i] = (byte)(Convert.ToInt32(value.Substring(i * 2, 2), 16));
            return ret;
        }

        /// <summary>
        /// 字节数组转结构
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="bytes"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public static T BytesToStruct<T>(byte[] bytes)
        {
            T result = default(T);
            try
            {
                int size = Marshal.SizeOf(typeof(T));
                //分配结构大小的内存空间
                IntPtr structPtr = Marshal.AllocHGlobal(size);
                //将byte数组拷到分配好的内存空间
                Marshal.Copy(bytes, 0, structPtr, size);
                //将内存空间转换为目标结构
                result = (T)Marshal.PtrToStructure(structPtr, typeof(T));
                //释放内存空间
                Marshal.FreeHGlobal(structPtr);
                //返回结构
            }
            catch
            {
                throw;
            }
            return result;
        }

        /// <summary>
        /// 判断double类型数据是否为零
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool IsZeroWithDouble(double value)
        {
            if (Math.Abs(value) < 0.0000001)
                return true;
            else
                return false;
        }

        /// <summary>
        /// 时间转为毫秒数
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static double DateTimeToMillisecond(DateTime time)
        {
            DateTime d = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            return (time - d).TotalMilliseconds;
        }

        /// <summary>
        /// 毫秒数转为时间
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        public static DateTime MillSecondToDateTime(double d)
        {
            DateTime result;
            try
            {
                DateTime dateTime = DateTime.MinValue;
                dateTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).AddMilliseconds(d);
                result = dateTime;
            }
            catch
            {
                result = DateTime.MinValue;
            }

            return result;
        }

        /// <summary>
        /// 计算子数组在源数组中第一次出现的位置
        /// </summary>
        /// <param name="src"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public  static int FindChildArrayFirst(List<byte> src, byte[] desc, int startIndex = 0)
        {
            for (int i = startIndex; i < src.Count; i++)
            {
                if (src[i] != desc[0]) continue;

                byte[] bytes = src.Skip(i).Take(desc.Length).ToArray();
                if (bytes != desc) return i;
            }
            return -1;
        }

        /// <summary>
        /// 滚动到ListBox最后一项
        /// </summary>
        /// <param name="box"></param>
        public static void ScrollToBottomForListBox(ListBox box)
        {
            if (VisualTreeHelper.GetChildrenCount(box) > 0)
            {
                Border border = (Border)VisualTreeHelper.GetChild(box, 0);
                ScrollViewer scrollViewer = (ScrollViewer)VisualTreeHelper.GetChild(border, 0);
                scrollViewer.ScrollToBottom();
            }
        }

        /// <summary>
        /// 按固定长度拆分字节数组
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="descLength">目标长度</param>
        /// <returns></returns>
        public static List<byte[]> SplitBytes(byte[] data, int descLength)
        {
            List<byte[]> arrlist = new List<byte[]>();
            int totalLength = data.Length;
            for (int i = 0; i < totalLength; i += descLength)
            {
                if (totalLength - i > descLength)//如果是，就截取
                {
                    arrlist.Add(data.Skip(i).Take(descLength).ToArray());
                }
                else
                {
                    arrlist.Add(data.Skip(i).ToArray());//如果不是，就截取最后剩下的那部分
                }
            }
            return arrlist;
        }

        /// <summary>
        /// 线程挂起，避免UI卡主
        /// </summary>
        public static void Delay(int mm)
        {
            DateTime current = DateTime.Now;
            while (current.AddMilliseconds(mm) > DateTime.Now)
            {
                DispatcherHelper.DoEvents();
            }
            return;
        }
    }
}
